Skip to content

Port: keep dungeon monster slots below the sub-game slots - #119

Closed
carrdylan52 wants to merge 1 commit into
TheMoonPeople:masterfrom
carrdylan52:pr/monster-scene-slots
Closed

carrdylan52 wants to merge 1 commit into
TheMoonPeople:masterfrom
carrdylan52:pr/monster-scene-slots

Conversation

@carrdylan52

Copy link
Copy Markdown
Contributor

Since the PR #59 merge (029e28e), entering any dungeon floor crashes, and so does New Game, because the opening is a dungeon scene. It happens with game.more_monsters on or off. 3c8c146 is fine; 029e28e and current master crash.

Cause. header_fixups.py raises MONSTER_ACTIVE_MAX to 60, so the active monsters occupy scene characters 24 to 83. Characters 64 to 103 are the sub-game slots (SUBGAME_CHARA_BASE). InitDungeonMain calls InitSubGame after binding the monsters, and that clears them, so monsters 40 to 59 are wiped. The floor script's LoadDungeonMapFile then runs CMonsterMan::Initialize, which always loops over all MONSTER_ACTIVE_MAX slots, reads slot 64 back as null, and faults at monster.cpp:778.

Fix. MONSTER_ACTIVE_MAX is now 40, so the slots end at character 63.

  • A floor's placement list holds at most 32 monsters (MONSTER_LOCATE_MAX), so the setting still opens a floor with as many monsters as before. It does lower the room for later spawns from 60 to 40.
  • Keeping 60 would mean moving the monster or sub-game slot ranges.
  • A static assert in port/src/monster.cpp keeps the range below SUBGAME_CHARA_BASE.
  • Docs and the option text now say 40.

Tests.

  • New gtest MonsterSlots.SurviveTheSubGameClear runs the real InitSubGame over a full 128-slot scene.
  • New Python test checks the mirrored constants.
  • Both new tests fail before the fix and pass after.
  • On Windows, --jump dungeon:0:1 and dungeon:1:1 with tools/input/jump-dungeon-floor1.input reach frame 2300 with more_monsters off and on, and --jump opening plays.
  • Full ctest: no new failures.

Merging PR TheMoonPeople#59 raised MONSTER_ACTIVE_MAX to 60 in the header mirror, so
the active monsters became scene characters 24 to 83. Scene characters
64 to 103 (SUBGAME_CHARA_BASE, SUBGAME_CHARA_NUM) belong to the sub-games,
and InitDungeonMain calls InitSubGame after binding the monsters, which
clears them. The floor script's LoadDungeonMapFile then runs
CMonsterMan::Initialize, which reads every one of the 60 slots back and
calls Initialize on monster 40's now-empty slot: a null dereference on
every dungeon entry, with game.more_monsters on or off, since the loop
runs to MONSTER_ACTIVE_MAX either way.

MONSTER_ACTIVE_MAX is now 40, so the slots end at scene character 63.
A floor's placement list holds at most 32 monsters, so the setting
still raises the opening count as far as before. A static assert in
port/src/monster.cpp holds the range below SUBGAME_CHARA_BASE; a unit
test runs InitSubGame over a full 128-slot scene and a header fixup
test checks the mirrored constants.
@carrdylan52

Copy link
Copy Markdown
Contributor Author

Closing, superseded by e537a63 (InitSubGame now keeps the monster-typed slots, so the cap can stay at 60). Same crash as #117.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant